package question.solution40;

import question.SolutionTemplate;

import java.lang.reflect.Array;
import java.util.*;

public class Solution40 implements SolutionTemplate {

    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        // 10,1,2,7,6,1,5 ==> 1,1,2,5,6,7,10
        List<List<Integer>> result = new ArrayList<>();
        if(candidates.length == 0){
            return result;
        }
        Arrays.sort(candidates);
        if(candidates[0] > target){
            return result;
        }
        if(candidates[0] == target){
            List<Integer> subResult = new ArrayList<>();
            subResult.add(candidates[0]);
            result.add(subResult);
            return result;
        }

        boolean[] pickIt = new boolean[candidates.length];
        Set<List<Integer>> resultSet = new HashSet<>();
        pickIt[0] = true;
        probe(candidates, pickIt, target - candidates[0], 1, resultSet);
        pickIt[0] = false;
        probe(candidates, pickIt, target, 1, resultSet);
        result = new ArrayList<>(resultSet);
        return result;
    }

    private boolean probe(int[] candidates, boolean[] pickIt, int target, int pickingIndex, Set<List<Integer>> resultSet){
        if(pickingIndex > candidates.length-1){
            return false;
        }
        if(candidates[pickingIndex] == target){
            boolean temp = pickIt[pickingIndex];
            pickIt[pickingIndex] = true;
            resultSet.add(getCandidatesWithCount(candidates, pickIt));
            pickIt[pickingIndex] = temp;
            return false;
        }else if(candidates[pickingIndex] > target){
            return false;
        }else{

            boolean temp = pickIt[pickingIndex];
            pickIt[pickingIndex] = true;
            probe(candidates, pickIt, target - candidates[pickingIndex], pickingIndex+1, resultSet);

            pickIt[pickingIndex] = false;
            probe(candidates, pickIt, target, pickingIndex+1, resultSet);

            pickIt[pickingIndex] = temp;
            return true;
        }
    }

    private List<Integer> getCandidatesWithCount(int[] candidates, boolean[] pickIt){
        List<Integer> group = new ArrayList<>();
        for(int j = 0 ;j<pickIt.length; j++){
            if(pickIt[j]){
                group.add(candidates[j]);
            }
        }
        return group;
    }

    public void test() {
//        int[] candidates = {10,1,2,7,6,1,5};
//        List<List<Integer>> result = combinationSum2(candidates, 8);
//        int[] candidates2 = {1};
//        List<List<Integer>> result = combinationSum2(candidates2, 1);
        int[] candidates2 = {1};
        List<List<Integer>> result = combinationSum2(candidates2, 2);
        return;
    }
}
